#include "linkqueue.h"

extern func_linklist fun_linklist;

// #ifndef null
// define null NULL
// #endif

/**
 * 通过下面的定义来选择队列饿模型的选择 
 * 如果定义 TAIL_HEADER，第一种模型
 * 如果不定义 TAIL_HEADER，第二种模型
 **/
// #define ABCDEFGH

/**
 * 功 能：
 *      创建一个队列
 * 参 数：
 *      无
 * 返回值：
 *      成功：操作句柄
 *      失败：NULL
 **/
LinkQueue *LinkQueue_Create(void)
{
    return fun_linklist.create();
}

/**
 * 功 能：
 *      插入元素，压队列
 * 参 数：
 *      queue：要操作的队列
 *      node : 要插入的元素，队列的业务节点
 * 返回值：
 *      成功：0
 *      失败：-1
 **/
int LinkQueue_Append(LinkQueue *queue, LinkQueueNode *node)
{
    if (queue == NULL || node == NULL)
        return -1;

    TLinkQueueNode *temp = NULL;
    int ret = 0;

    temp = (TLinkQueueNode *)malloc(sizeof(TLinkQueueNode));
    if (temp == NULL)
        return -1;

    memset(temp, 0, sizeof(TLinkQueueNode));

    temp->item = node;
#ifdef ABCDEFGH
    ret = fun_linklist.insert(queue, (LinkListNode *)temp, fun_linklist.length(queue));
#else
    ret = fun_linklist.insert(queue, (LinkListNode *)temp, 0);
#endif
    if (ret != 0 && temp != NULL)
        free(temp);

    return ret;
}

/**
 * 功 能：
 *      弹出队列元素
 * 参 数：
 *      queue：要操作的队列
 * 返回值：
 *      成功：删除后的元素
 *      失败：NULL
 **/
LinkQueueNode *LinkQueue_Subtract(LinkQueue *queue)
{
    if (queue == NULL)
        return NULL;

    LinkQueueNode *item = NULL;
    TLinkQueueNode *temp = NULL;

#ifdef ABCDEFGH
    temp = (TLinkQueueNode *)fun_linklist.delete(queue, 0);
#else
    temp = (TLinkQueueNode *)fun_linklist.delete(queue, fun_linklist.length(queue) - 1);
#endif
    if (temp == NULL)
        return NULL;

    // 把线性表的业务节点转换成队列的业务节点
    item = temp->item;
    // 在 insert 的时候malloc的内存需要free掉
    if (temp != NULL)
        free(temp);

    return item;
}

/**
 * 功 能：
 *      清空一个队列
 * 参 数：
 *      queue：要操作的队列
 * 返回值：
 *      成功：0
 *      失败：-1
 **/

int LinkQueue_Clear(LinkQueue *queue)
{
    if (queue == NULL)
        return -1;

    while (fun_linklist.length(queue) > 0)
    {
        /*
            涉及到队列的元素声明周期的处理
            所有入队列的节点都是通过mallo静态申请的，那么想要清空队列的时候，需要将malloc的节点free掉
            所以需要将队列中元素全都pop掉，并且free节点的内存
        */
        LinkQueueNode *temp = LinkQueue_Subtract(queue);
        if (temp == NULL)
        {
            return -1;
        }
    }
    return 0;
}

/**
 * 功 能：
 *      销毁一个队列
 * 参 数：
 *      queue：要操作的队列
 * 返回值：
 *      成功：0
 *      失败：-1
 **/
int LinkQueue_Destory(LinkQueue *queue)
{
    LinkQueue_Clear(queue);
    return fun_linklist.destory(&queue);
}

/**
 * 功 能：
 *      获取队列的长度
 * 参 数：
 *      queue：要操作的队列
 * 返回值：
 *      成功：队列的长度
 *      失败：-1
 **/
int LinkQueue_Length(LinkQueue *queue)
{
    return fun_linklist.length(queue);
}

/**
 * 功 能：
 *      获取队列顶的元素
 * 参 数：
 *      queue：要操作的队列
 * 返回值：
 *      成功：操作句柄
 *      失败：NULL
 **/
LinkQueueNode *LinkQueue_Header(LinkQueue *queue)
{
    if (queue == NULL)
        return NULL;
    TLinkQueueNode *temp = NULL;
#ifdef ABCDEFGH
    temp = (TLinkQueueNode *)fun_linklist.get(queue, 0);
#else
    temp = (TLinkQueueNode *)fun_linklist.get(queue, fun_linklist.length(queue) - 1);
#endif

    if (temp == NULL)
        return NULL;

    return temp->item;
}

func_LinkQueue fLinkQueue = {
    LinkQueue_Create,
    LinkQueue_Destory,
    LinkQueue_Clear,
    LinkQueue_Length,
    LinkQueue_Append,
    LinkQueue_Header,
    LinkQueue_Subtract};
